﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OpCompare
{
    public partial class FormMain : Form
    {
        private List<FileInfo> DiffFile { get; set; }
        private List<FileInfo> SameFile { get; set; }
        private List<FileInfo> DiffFileRe { get; set; }
        private List<FileInfo> SameFileRe { get; set; }
        private decimal ov { get; set; }
        public static SessionObj currentSession { get; set; }
        public static string cfgpath = Application.StartupPath + "\\config.json";
        public static List<SessionObj> Sessions { get; set; }

        public delegate void TransfDelegate(SessionObj value);
        public FormMain()
        {
            InitializeComponent();
            string Cfg = FileHelper.TxtRead(cfgpath);
            Sessions = JsonConvert.DeserializeObject<List<SessionObj>>(Cfg);
            if (currentSession != null)
                this.Text += "--" + currentSession.name;
        }

        private void ToolbtnLocal_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog path = new FolderBrowserDialog();
            if (path.ShowDialog() == DialogResult.OK)
            {
                this.localPath.Text = path.SelectedPath;
            }            
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            DiffFile = new List<FileInfo>();
            SameFile = new List<FileInfo>();
            DiffFileRe = new List<FileInfo>();
            SameFileRe = new List<FileInfo>();

            this.listViewLeft.View = View.Details;
            listViewLeft.Columns.Add("名称", 280, HorizontalAlignment.Left);
            listViewLeft.Columns.Add("大小", 50, HorizontalAlignment.Center);
            listViewLeft.Columns.Add("修改时间", 150, HorizontalAlignment.Right);

            this.listViewRight.View = View.Details;
            listViewRight.Columns.Add("名称", 280, HorizontalAlignment.Left);
            listViewRight.Columns.Add("大小", 50, HorizontalAlignment.Center);
            listViewRight.Columns.Add("修改时间", 150, HorizontalAlignment.Right);

            ov = Convert.ToDecimal(localPath.Width) / Convert.ToDecimal(this.Width);
        }

        private void LocalPath_TextChanged(object sender, EventArgs e)
        {
            try
            {
                DirectoryInfo TheFolder = new DirectoryInfo(this.localPath.Text);
                FileInfo[] FileList = TheFolder.GetFiles();
                DirectoryInfo[] DirList = TheFolder.GetDirectories();

                List<string> ignorelists = new List<string>();
                if (currentSession!=null && currentSession.ignoreFiles != null)
                    ignorelists = JsonConvert.DeserializeObject<List<string>>(currentSession.ignoreFiles);

                this.listViewLeft.Items.Clear();
                this.listViewLeft.BeginUpdate();
                foreach (DirectoryInfo NextDir in DirList)
                {
                    ListViewItem additem = new ListViewItem();
                    additem.ImageIndex = 1;
                    additem.Text = NextDir.Name;
                    additem.Tag = NextDir;
                    additem.SubItems.Add("");
                    additem.SubItems.Add(NextDir.LastWriteTime.ToString());
                    this.listViewLeft.Items.Add(additem);
                }
                foreach (FileInfo NextFile in FileList)
                {
                    if (!ignorelists.Contains(NextFile.Name))
                    {
                        ListViewItem additem = new ListViewItem();
                        additem.ImageIndex = 0;
                        additem.Text = NextFile.Name;
                        additem.Tag = NextFile;
                        additem.SubItems.Add(NextFile.Length.ToString());
                        additem.SubItems.Add(NextFile.LastWriteTime.ToString());
                        this.listViewLeft.Items.Add(additem);
                    }
                }
                this.listViewLeft.EndUpdate();
                SetRowBgColor(listViewLeft);
                statusTxt.Text = "左边共：" + FileList.Count().ToString() + "个文件";
                statusTxtIgnore.Text = ignorelists.Count + "个忽略文件";
            }
            catch { }
        }

        private void RemotePath_TextChanged(object sender, EventArgs e)
        {
            try
            {
                DirectoryInfo TheFolder = new DirectoryInfo(this.remotePath.Text);
                FileInfo[] FileList = TheFolder.GetFiles();
                DirectoryInfo[] DirList = TheFolder.GetDirectories();
                this.listViewRight.Items.Clear();
                this.listViewRight.BeginUpdate();
                foreach (DirectoryInfo NextDir in DirList)
                {
                    ListViewItem additem = new ListViewItem();
                    additem.ImageIndex = 1;
                    additem.Text = NextDir.Name;
                    additem.Tag = NextDir;
                    additem.SubItems.Add("");
                    additem.SubItems.Add(NextDir.LastWriteTime.ToString());
                    this.listViewRight.Items.Add(additem);
                }
                foreach (FileInfo NextFile in FileList)
                {
                    ListViewItem additem = new ListViewItem();
                    additem.ImageIndex = 0;
                    additem.Text = NextFile.Name;
                    additem.Tag = NextFile;
                    additem.SubItems.Add(NextFile.Length.ToString());
                    additem.SubItems.Add(NextFile.LastWriteTime.ToString());
                    this.listViewRight.Items.Add(additem);
                }
                this.listViewRight.EndUpdate();
                SetRowBgColor(listViewRight);
                statusTxt2.Text = "右边共：" + FileList.Count().ToString() + "个文件";
            }
            catch { }
        }

        private void ToolBtnRemote_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog path = new FolderBrowserDialog();
            if (path.ShowDialog() == DialogResult.OK)
            {
                this.remotePath.Text = path.SelectedPath;
            }
        }

        private void SetRowBgColor(ListView listV)
        {
            for (int i = 0; i < listV.Items.Count; i++)
            {
                if (i % 2 == 0)
                {
                    for (int j = 0; j < listV.Items[i].SubItems.Count; j++)
                    {
                        listV.Items[i].SubItems[j].BackColor = Color.WhiteSmoke;
                    }
                }
                else
                {
                    for (int j = 0; j < listV.Items[i].SubItems.Count; j++)
                    {
                        listV.Items[i].SubItems[j].BackColor = Color.White;
                    }
                }
                listV.Items[i].UseItemStyleForSubItems = true;
            }
        }

        private void ToolDifferent_Click(object sender, EventArgs e)
        {
            DiffFile = new List<FileInfo>();
            SameFile = new List<FileInfo>();
            for (int i = 0; i < listViewLeft.Items.Count; i++)
            {
                if (listViewLeft.Items[i].ImageIndex == 0)
                {
                    FileInfo lft = listViewLeft.Items[i].Tag as FileInfo;
                    if (CheckDiff(lft, listViewRight))
                    {
                        DiffFile.Add(lft);
                        listViewLeft.Items[i].SubItems[0].ForeColor = Color.Red;
                    }
                    else
                    {
                        SameFile.Add(lft);
                        listViewLeft.Items[i].SubItems[0].ForeColor = Color.Blue;
                    }
                }
            }
            for (int i = 0; i < listViewRight.Items.Count; i++)
            {
                if (listViewRight.Items[i].ImageIndex == 0)
                {
                    FileInfo rgt = listViewRight.Items[i].Tag as FileInfo;
                    if (CheckDiff(rgt, listViewLeft))
                    {
                        DiffFileRe.Add(rgt);
                        listViewRight.Items[i].SubItems[0].ForeColor = Color.Red;
                    }
                    else
                    {
                        SameFileRe.Add(rgt);
                        listViewRight.Items[i].SubItems[0].ForeColor = Color.Blue;
                    }
                }
            }
            statusText.Text = DiffFile.Count + "个文件有差异。" + SameFile.Count + "个文件相同。";
        }

        private bool CheckDiff(FileInfo lft, ListView listV)
        {
            bool result = false;
            bool isExist = false;
            FileInfo rgtFile = lft;
            for (int k = 0; k < listV.Items.Count; k++)
            {
                if (listV.Items[k].ImageIndex == 0)
                {
                    FileInfo rgt = listV.Items[k].Tag as FileInfo;
                    if (lft.Name == rgt.Name)
                    {
                        rgtFile = rgt;
                        isExist = true;
                        break;
                    }
                }
            }
            if (isExist)
            {
                if (rgtFile.Length != lft.Length || rgtFile.LastWriteTime != lft.LastWriteTime)
                {
                    result = true;
                }
            }
            else
            {
                result = true;
            }
            return result;
        }
        
        private async void ToolSMenu_Upload_Click(object sender, EventArgs e)
        {
            try
            {
                ToolSMenu_Upload.Enabled = false;
                string remotePath = this.remotePath.Text.Trim();
                remotePath = remotePath.EndsWith(@"\") ? remotePath : remotePath + @"\";
                await Task.Run(() =>
                {
                    foreach (FileInfo NextFile in DiffFile)
                    {
                        File.Copy(NextFile.FullName, remotePath + NextFile.Name, true);
                        statusText.Text = NextFile.Name + "复制成功。";
                    }
                });

                LocalPath_TextChanged(sender, e);
                RemotePath_TextChanged(sender, e);
                ToolDifferent_Click(sender, e);

                ToolSMenu_Upload.Enabled = true;
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                ToolSMenu_Upload.Enabled = true;
            }
        }

        private async void ToolSMenu_Download_Click(object sender, EventArgs e)
        {
            ToolSMenu_Download.Enabled = false;
            string localPath = this.localPath.Text.Trim();
            localPath = localPath.EndsWith(@"\") ? localPath : localPath + @"\";
            await Task.Run(() =>
            {
                foreach (FileInfo NextFile in DiffFileRe)
                {
                    File.Copy(NextFile.FullName, localPath + NextFile.Name, true);
                    statusText.Text = NextFile.Name + "复制成功。";
                }
            });
            
            LocalPath_TextChanged(sender, e);
            RemotePath_TextChanged(sender, e);
            ToolDifferent_Click(sender, e);
            ToolSMenu_Download.Enabled = true;
        }

        private void ToolAll_Click(object sender, EventArgs e)
        {
            LocalPath_TextChanged(sender, e);
            RemotePath_TextChanged(sender, e);
            ToolDifferent_Click(sender, e);
        }

        private void FormMain_SizeChanged(object sender, EventArgs e)
        {
            int newLen = toolStripLeft.Width - 85; //Convert.ToInt32(ov * this.Width);
            localPath.Size = remotePath.Size = new Size(newLen, localPath.Height);
            toolStripLeft.Refresh();
            toolStripRight.Refresh();
        }

        void frm_TransfEvent(SessionObj value)
        {
            this.Text = "当前会话：" + value.name;
            this.localPath.Text = value.localPath;
            this.remotePath.Text = value.remotePath;
        }

        private void ToolMenuItem_Save_Click(object sender, EventArgs e)
        {            
            SessionObj obj = new SessionObj();
            obj.localPath = localPath.Text;
            obj.remotePath = remotePath.Text;
            obj.name = currentSession != null ? currentSession.name : "";

            var btn = sender as ToolStripMenuItem;
            FormSession form = new FormSession(obj, btn.Text);
            form.TransfEvent += frm_TransfEvent;
            form.ShowDialog();
        }

        private void ToolMenuItem_SaveAs_Click(object sender, EventArgs e)
        {
            SessionObj obj = new SessionObj();
            obj.localPath = localPath.Text;
            obj.remotePath = remotePath.Text;
            obj.name = "New";
            var btn = sender as ToolStripMenuItem;
            FormSession form = new FormSession(obj, btn.Text);
            form.TransfEvent += frm_TransfEvent;
            form.ShowDialog();
        }

        private void ToolMenuItem_Open_Click(object sender, EventArgs e)
        {
            var btn = sender as ToolStripMenuItem;
            FormSession form = new FormSession(currentSession, btn.Text);
            form.TransfEvent += frm_TransfEvent;
            form.ShowDialog();
        }

        private void ToolSame_Click(object sender, EventArgs e)
        {

        }

        private void ListViewLeft_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            var folder = listViewLeft.SelectedItems[0];
            if (folder.ImageIndex == 1)
            {
                var dir = folder.Tag as DirectoryInfo;
                localPath.Text += @"\" + dir.Name;
                remotePath.Text += @"\" + dir.Name;
            }
        }

        private void ListViewRight_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            var folder = listViewRight.SelectedItems[0];
            if (folder.ImageIndex == 1)
            {
                var dir = folder.Tag as DirectoryInfo;
                remotePath.Text += @"\" + dir.Name;
                localPath.Text += @"\" + dir.Name;
            }
        }

        private void LocalDirUp_Click(object sender, EventArgs e)
        {
            string[] lPath = localPath.Text.Split('\\');
            if (lPath.Length > 1)
            {
                string newPath = localPath.Text.Replace(@"\" + lPath[lPath.Length - 1], "");
                localPath.Text = newPath;
                newPath = remotePath.Text.Replace(@"\" + lPath[lPath.Length - 1], "");
                remotePath.Text = newPath;
            }
        }

        private void RemoteDirUp_Click(object sender, EventArgs e)
        {
            string[] lPath = remotePath.Text.Split('\\');
            if (lPath.Length > 1)
            {
                string newPath = remotePath.Text.Replace(@"\" + lPath[lPath.Length - 1], "");
                remotePath.Text = newPath;
                newPath = localPath.Text.Replace(@"\" + lPath[lPath.Length - 1], "");
                localPath.Text = newPath;
            }
        }

        private void ToolSMenu_ignore_Click(object sender, EventArgs e)
        {
            var selected = this.listViewLeft.SelectedItems;
            List<string> lists = new List<string>();
            if (currentSession == null) return;
            if (currentSession!=null && currentSession.ignoreFiles != null)
                lists = JsonConvert.DeserializeObject<List<string>>(currentSession.ignoreFiles);
            foreach (ListViewItem item in selected)
            {                
                lists.Add(item.Text);
            }
            currentSession.ignoreFiles = JsonConvert.SerializeObject(lists);
            var sessions = Sessions.Where(o => o.name != currentSession.name).ToList();
            sessions.Add(currentSession);
            string jsons = JsonConvert.SerializeObject(sessions);
            FileHelper.TxtWrite(FormMain.cfgpath, jsons);
            MessageBox.Show("添加成功！");
            LocalPath_TextChanged(sender, e);
        }

        private void statusTxtIgnore_Click(object sender, EventArgs e)
        {
            if (currentSession != null && Sessions != null)
            {
                FormIgnore form = new FormIgnore(currentSession, Sessions);
                form.ShowDialog();
                form.Owner = this;
            }
        }
    }
    public class SessionObj
    {
        public string localPath { get; set; }
        public string remotePath { get; set; }
        public string name { get; set; }
        public string ignoreFiles { get; set; }
    }
}
